/*
 * FileIPPool.java Created on 30 Январь 2006 г., 19:58 To change this template,
 * choose Tools | Template Manager and open
 * the template in the editor.
 */

package org.dicr.util.net.ippool;

import java.io.*;
import java.util.*;

import org.apache.log4j.*;
import org.dicr.util.data.exc.*;
import org.dicr.util.net.*;

/**
 * File IP Pool. Serialize persistent data in file.
 * 
 * @author Igor A Tarasov &lt;linux@dicr.org&gt;
 * @version 060619
 */
public class FileIPPool extends AbstractIPPool {

	private static final Logger log = Logger.getLogger(FileIPPool.class);

	/** File to store */
	protected File file = null;

	/** IPs cache */
	protected Set<IP> allocated = null;

	/**
	 * Constructor
	 */
	public FileIPPool() {
		super();
	}

	/**
	 * Constructor
	 * 
	 * @param theFile
	 *            file to store ips
	 */
	public FileIPPool(final File theFile) {
		super();
		this.setFile(theFile);
	}

	/**
	 * Constructor
	 * 
	 * @param fileName
	 *            file name to store IPs
	 */
	public FileIPPool(final String fileName) {
		super();
		this.setFile(fileName);
	}

	/**
	 * Set file to store IPs
	 * 
	 * @param theFile
	 *            file to store IPs
	 */
	public void setFile(final File theFile) {
		if (theFile == null) throw new IllegalArgumentException("null file");
		this.file = theFile.getAbsoluteFile();
	}

	/**
	 * Set file to store IPs
	 * 
	 * @param fileName
	 *            file name to store
	 */
	public void setFile(final String fileName) {
		if (fileName == null) throw new IllegalArgumentException("null fileName");
		this.setFile(new File(fileName));
	}

	/**
	 * Return file.
	 * 
	 * @return file in which IPs are stored.
	 */
	public File getFile() {
		return this.file;
	}

	/**
	 * Load data from file
	 * 
	 * @return allocated IPs
	 * @throws StorageException
	 *             if data load error
	 */
	@SuppressWarnings("unchecked")
	@Override
	public synchronized Set<IP> getAllocatedIps() throws StorageException {
		if (this.allocated != null) return new HashSet<>(this.allocated);
		// check file
		if (!this.file.exists()) this.allocated = new HashSet<>();
		else {
			// load file data
			ObjectInputStream in = null;
			try {
				in = new ObjectInputStream(new FileInputStream(this.file));
				this.allocated = (Set<IP>) in.readObject();
				FileIPPool.log.trace("allocated ips loaded from file: " + this.file.getAbsolutePath());
			} catch (final IOException ex) {
				throw new StorageException(ex);
			} catch (final ClassNotFoundException ex) {
				throw new StorageException(ex);
			} finally {
				try {
					if (in != null) in.close();
				} catch (final Exception ex) {
					// nop
				}
			}
		}
		return this.allocated;
	}

	/**
	 * Store allocated IPs in file
	 * 
	 * @param theAllocated
	 *            allocated ips
	 * @throws StorageException
	 *             if save data error
	 */
	@Override
	protected synchronized void sotreAllocatedIPs(final Set<IP> theAllocated) throws StorageException {
		if (theAllocated == null) throw new IllegalArgumentException("null allocated");
		this.allocated = new HashSet<>(theAllocated);
		ObjectOutputStream ou = null;
		try {
			ou = new ObjectOutputStream(new FileOutputStream(this.file));
			ou.writeObject(this.allocated);
			FileIPPool.log.trace("allocated ips stored in file: " + this.file.getAbsolutePath());
		} catch (final IOException ex) {
			throw new StorageException(ex);
		} finally {
			try {
				if (ou != null) ou.close();
			} catch (final Exception ex) {
				// nop
			}
		}
	}
}
